package io.seata.sample.service;

import io.seata.core.context.RootContext;
import io.seata.sample.dao.OrderDao;
import io.seata.sample.entity.Order;
import io.seata.sample.feign.AccountApi;
import io.seata.sample.feign.StorageApi;
import io.seata.spring.annotation.GlobalTransactional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

/**
 * @author wangzhen
 */
@Service("orderServiceImpl")
public class OrderServiceImpl implements OrderService {

    private static final Logger LOGGER = LoggerFactory.getLogger(OrderServiceImpl.class);

    @Autowired
    private OrderDao orderDao;
    @Autowired
    private StorageApi storageApi;
    @Autowired
    private AccountApi accountApi;

    /**
     * 创建订单
     *
     * @param order
     * @return 测试结果：
     * 1.添加本地事务：仅仅扣减库存
     * 2.不添加本地事务：创建订单，扣减库存
     */
    @Override
    @GlobalTransactional(name = "order-server", rollbackFor = Exception.class)
    @Transactional(rollbackFor = Exception.class)
    public void create(Order order) {

        String xid = RootContext.getXID();
        LOGGER.info("------->交易开始");
        LOGGER.info("------->全局事务 xid： {}", xid);
        //本地方法
        orderDao.create(order);

        //远程方法 扣减库存
        storageApi.decrease(order.getProductId(), order.getCount());

        //折扣
        BigDecimal money = order.getMoney();
        BigDecimal discount = money.multiply(new BigDecimal("0.1"));

        //远程方法 扣减账户余额
        accountApi.decrease(order.getUserId(), money.subtract(discount));

        //交易完成修改订单状态，以及最终价格
        update(order.getUserId(), money.subtract(discount), order.getId());

        LOGGER.info("------->交易结束");
        LOGGER.info("全局事务 xid： {}", xid);
    }

    /**
     * 修改订单状态
     */
    @Override
    public void update(Long userId, BigDecimal money, Long orderId) {
        LOGGER.info("修改订单状态，入参为：userId={},money={},orderId={}", userId, money, orderId);
        orderDao.update(userId, money, orderId);
    }
}
